/**
 * 给定一个数字字符串，问有多少个区间通过重排可以形成回文数。
 * 考虑偶数长度的区间，重排可以形成回文数实际上就是要求区间内所有元素的数量均为偶数
 * 再进一步可知具体数量没有意义，只有奇偶有意义，因此就用0和1表示，用一位就够了
 * 一共有10种数字，因此用二进制表示，Di表示S[1...i]中数字数量的奇偶性
 * 例如 S[1...i] 中有奇数个1，则Di的第1位就为1；有偶数个5，则Di的第5位就为0。
 * 
 * for i in [0...N]:
 *     令 d = D[i]
 *     令 c是i之前d出现的次数, 则 ans += c
 *     再令 t 是与 d 二进制位只有1位不同的, c 是 t 之前出现的次数， 则 ans += c
 * 
 * 最后ans是答案 
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;

int N;
string S;
vi D;


llt proc(){
    N = S.length();
    S = " " + S;
    D.assign(N + 1, 0);
    for(int i=1;i<=N;++i){
        int tmp = S[i] - '0';
        D[i] = D[i - 1] ^ (1 << tmp);
    }    

    llt ans = 0;
    map<int, int> cnt;
    for(int i=0;i<=N;i+=1){
        auto d = D[i];
        auto it = cnt.find(d);
        if(it == cnt.end()) it = cnt.insert(it, {d, 1});
        else ++it->second;

        ans += it->second - 1;
        for(int i=0;i<10;++i){
            int t = d ^ (1 << i);
            auto it = cnt.find(t);
            if(it != cnt.end()){
                ans += it->second;
            }
        }        
    }

    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1; 
    // cin >> nofkase;
    while(nofkase--){
        cin >> S;
        cout << proc() << "\n";
    }
    return 0;
}